#pragma once
#include <cstring>
#include <memory>

namespace StringVariants {

  /**
   * @brief 简化版写时复制字符串（Copy-on-Write）。
   *
   *  - 用 std::shared_ptr 管理共享缓冲区。
   *  - 写操作前通过 unique() 判断是否需要分离。
   *  - 仅用于演示或 Benchmark，对异常安全与性能未做深入处理。
   */
  class CowStringSimple {
  public:
    /**
     * @brief 默认构造为空字符串。
     */
    CowStringSimple() : buf_(make_buffer("", 0)) {}

    /**
     * @brief 通过 C 风格字符串初始化。
     *
     * @param s 输入字符序列，若为 nullptr 则视为长度 0。
     */
    explicit CowStringSimple(const char *s) {
      std::size_t len = s ? std::strlen(s) : 0;
      buf_ = make_buffer(s ? s : "", len);
    }

    /**
     * @brief 在字符串尾部追加单个字符，写操作会确保独占缓冲。
     *
     * @param c 需要追加的字符。
     */
    void push_back(char c) {
      detach_if_shared();
      if (buf_->size == buf_->capacity) {
        grow(buf_->capacity ? buf_->capacity * 2 : 8);
      }
      buf_->data[buf_->size++] = c;
      buf_->data[buf_->size] = '\0';
    }

    /**
     * @brief 获取 C 风格的字符串视图。
     */
    const char *c_str() const { return buf_->data.get(); }

    /**
     * @brief 当前字符串长度。
     */
    std::size_t size() const { return buf_->size; }

  private:
    /**
     * @brief 内部缓冲区结构体，保存数据指针及容量信息。
     */
    struct Buffer {
      std::unique_ptr<char[]> data; ///< 实际字符数据的拥有指针。
      std::size_t size;             ///< 已使用的字符数量。
      std::size_t capacity;         ///< 当前缓冲区容量。
    };

    /**
     * @brief 创建一个新的缓冲区并拷贝初始内容。
     *
     * @param src 初始数据源。
     * @param len 初始长度。
     */
    static std::shared_ptr<Buffer> make_buffer(const char *src, std::size_t len) {
      auto buffer = std::make_shared<Buffer>();
      buffer->data = std::make_unique<char[]>(len + 1);
      buffer->size = buffer->capacity = len;
      if (len) std::memcpy(buffer->data.get(), src, len);
      buffer->data[len] = '\0';
      return buffer;
    }

    /**
     * @brief 若缓冲区被多个所有者共享，则复制一份实现写时分离。
     */
    void detach_if_shared() {
      if (!buf_.unique()) {
        buf_ = make_buffer(buf_->data.get(), buf_->size);
      }
    }

    /**
     * @brief 扩展缓冲区容量并保留旧数据。
     *
     * @param new_cap 新的容量大小。
     */
    void grow(std::size_t new_cap) {
      auto new_buf = std::make_unique<char[]>(new_cap + 1);
      std::memcpy(new_buf.get(), buf_->data.get(), buf_->size + 1);
      buf_->data.swap(new_buf);
      buf_->capacity = new_cap;
    }

    std::shared_ptr<Buffer> buf_; ///< 共享的字符串缓冲区。
  };

} // namespace StringVariants